﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PServiceBus.Core.Interface;
using System.Collections;

namespace PServiceBus.Core.Provider {
    public sealed class ObjectProvider<TObject> : IObjectProvider<TObject> where TObject : class {

        private IList<TObject> _list;

        public ObjectProvider() {
            _list = new List<TObject>();
        }

        #region IObjectProvider<TObject> Members

        public bool Add(IEnumerable<TObject> list) {
            foreach (var obj in list) _list.Add(obj);
            return true;
        }

        public bool Refresh(TObject obj) {
            var id = IDFunc(obj);
            var removeObj = _list.Where(o => IDFunc(o) == id).Select((data,i) => new {Index = i}).FirstOrDefault();
            if (removeObj != null) _list.RemoveAt(removeObj.Index);
            return Add(obj);
        }

        public bool Add(TObject obj) {
            _list.Add(obj);
            return true;
        }

        public void Clear() {
            _list.Clear();
        }

        public void Delete() {
            Clear();
        }

        public bool Delete(IEnumerable<TObject> list) {
            _list = _list.Where(obj => !list.Any(o => o.Equals(obj))).ToList();
            return true;
        }

        public bool Delete(IEnumerable<Func<TObject, bool>> conditions) {
            _list = _list.Where(obj => !conditions.Any(condition => condition(obj))).ToList();
            return true;
        }

        public bool Delete(Func<TObject, bool> condition) {
            _list = _list.Where(obj => !condition(obj)).ToList();
            return true;
        }

        public bool Exists(Func<TObject, bool> condition) {
            return Get(condition) != null;
        }

        public TObject Get(Func<TObject, bool> condition) {
            return _list.FirstOrDefault(condition);
        }

        public bool Exists(TObject obj) {
            var id = IDFunc(obj);
            return this.Any(o => IDFunc(o) == id);
        }

        public TObject Get(Guid id) {
            return this.FirstOrDefault(obj => IDFunc(obj) == id);
        }

        public bool Delete(TObject obj) {
            var id = IDFunc(obj);
            _list = _list.Where(o => IDFunc(o) != id).ToList();
            return true;
        }

        public string Endpoint { get; set; }

        public string EndpointAlias { get; set; }

        public bool AppendTypeNameToEndpoint { get; set; }

        public bool DeleteObjectOnRead { get; set; }

        public Func<TObject, Guid> IDFunc { get; set; }
        #endregion

        #region IEnumerable<TObject> Members

        public IEnumerator<TObject> GetEnumerator() {
            for (var i = 0; i < _list.Count; i++) {
                var obj = _list[i];
                yield return obj;
                if (DeleteObjectOnRead) Delete(o => o.Equals(obj));
            }
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }

        #endregion

        #region IDisposable Members

        public void Dispose() {
        }

        #endregion
    }
}
